home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / mslang / itemli / itemlist.c next >
Encoding:
C/C++ Source or Header  |  1993-11-13  |  12.8 KB  |  475 lines

  1. /***********************************************************************
  2.     ITEMLIST
  3.  
  4.     Written by David Stroud  75165,421    11/13/93    
  5.     
  6.     This module is a standalone, independent set of calls that provide
  7.     an application a method to manage a last file loaded list facility.  
  8.     It uses a dynamically allocated list of filenames with which to 
  9.     manage the Windows menu calls.  The module can be included in any
  10.     application that requires managing 'last called' lists and is 
  11.     particularly useful when dealing with documents, files, and 
  12.     data sets.
  13.     
  14.     To initialize, ItemListInit must be called to set the following 
  15.     parameters:
  16.     
  17.     szDefaultDir = If you are using filenames, this is the name of the 
  18.                    directory that will be trimmed out of the filename 
  19.                    when it is added.  This can be suppressed, and is
  20.                    ignored by passing a "" (zero length string).  
  21.                    
  22.     uMaxItems    = The number of items to be stacked. Memory is allocated 
  23.                    based on this value.
  24.                    
  25.     uSubMenu     = The sub menu to be appended to.  
  26.  
  27.     Typical usage for a 'last file loaded':
  28.     
  29.     ItemListInit ("C:\MYDIR", 5, 0);              // Inits memory and globals
  30.     ItemListLoad ( GetMenu(hWndMain), "MY.INI");// Load element from the INI
  31.     ....
  32.     ItemListAdd  ( GetMenu(hWndMain), "THISFILE.TXT");    // Add an element
  33.     ....
  34.     ....
  35.     ItemListSave ( GetMenu(hWndMain), "MY.INI");// Save the elements to INI
  36.     ItemListCleanup();                            // Release memory/cleanup
  37.     
  38.     
  39.     Remember, it is up to you to do the following:
  40.     
  41.         1. Initialize...
  42.         2. Load defaults from your INI file...
  43.         3. Add items...they always 'rise to the top' avoiding explicit dups
  44.         4. Remove items...
  45.         5. Save defaults to your INI file
  46.         6. CLEAN UP MEMORY
  47.         
  48.     This module was written and compiled using Microsoft Visual C++ 1.0.
  49. ***************************************************************************/
  50.  
  51. #include <windows.h>
  52. #include <ctype.h>
  53. #include <string.h>
  54. #include "itemlist.h"
  55.  
  56. // Menu array tag
  57. typedef struct _itemtag {
  58.     char    szFile[ITEM_MAXLEN];
  59. } ITEMLIST;
  60.  
  61. // Pointer to menu array
  62. typedef ITEMLIST    FAR *LPITEMLIST;
  63.  
  64. static    HANDLE        hMemITEM = NULL;    // Handle to memory for alloc
  65. static    LPITEMLIST    lpitem;                // Pointer to first element
  66. static    char        szDefaultDir[128];    // Default directory
  67. static    UINT        uMaxItems = 3;        // Maximum number of menu items 
  68. static    UINT        uSubMenu = 0;        // Default menu is menu 0
  69.  
  70. // Private prototype declarations
  71. UINT ItemListSet ( HMENU hMenu, LPSTR lpentry, UINT uItem );
  72. UINT ItemListFind (HMENU hMenu, LPSTR lpentry);
  73. VOID ItemListRestackMenu ( HMENU hMenu );
  74. VOID upcase(LPSTR lpszStr);
  75. UINT ItemListAddSeparator(HMENU hMenu);
  76. UINT ItemListRemoveSeparator (HMENU hMenu);
  77. BOOL ItemListHasSeparator (HMENU hMenu);
  78. VOID ItemListFilenameCleanup(LPSTR lpfile);
  79.  
  80. /**********************************************************
  81.     ItemListInit
  82.     
  83.     Initialize default directory, maximum number of
  84.     items, and menu number.  Allocate memory area based
  85.     on the number of items allowed.
  86.     
  87.     Returns number allocated if successful, 0 if not
  88. **********************************************************/
  89. UINT ItemListInit (LPSTR lpdfdir, UINT uMax, UINT uMenu )
  90. {
  91.     upcase(lpdfdir);            // Force upper always
  92.  
  93.     if (uMax > ITEM_MAXFILES)        // No more than predefined allowed
  94.         uMax = ITEM_MAXFILES;
  95.     
  96.     // Initialize global static variables    
  97.     uMaxItems = uMax;
  98.     uSubMenu  = uMenu;
  99.     lstrcpy ( szDefaultDir, lpdfdir );
  100.     
  101.     if ((hMemITEM  = GlobalAlloc ( GHND, (DWORD)((uMax+1) * (DWORD)sizeof(ITEMLIST)))) == NULL)
  102.         return 0;
  103.  
  104.     if ((lpitem = (LPITEMLIST)GlobalLock ( hMemITEM ))==NULL)
  105.         return 0;
  106.         
  107.     return uMax;
  108. }
  109.  
  110. /**********************************************************
  111.     ItemListCleanup
  112.     
  113.     Release memory.  Always returns 1.
  114.     
  115. **********************************************************/
  116. UINT ItemListCleanup(VOID)
  117. {
  118.     GlobalUnlock (hMemITEM);
  119.     GlobalFree   (hMemITEM);
  120.     return 1;
  121. }
  122.             
  123. /**********************************************************
  124.     ItemListLoad
  125.     
  126.     Loads the file keys from the ini filename that is 
  127.     passed.  Initializes the menu after the load occurs.
  128.     
  129.     Returns number of items attached to the sub menu
  130.     
  131. **********************************************************/
  132. UINT ItemListLoad (HMENU hMenu, LPSTR lpinifile )
  133. {
  134.     UINT    uCount = 0;
  135.     UINT    i;
  136.     char    szKey[20];
  137.     char    szTemp[ITEM_MAXLEN];
  138.                         
  139.     // If the user forgot to initialize, then we do that
  140.     // for them here using the number of defaults declared
  141.     // for the global statics
  142.     if (hMemITEM == NULL)    
  143.         ItemListInit ("\\",uMaxItems,uSubMenu);
  144.     
  145.     // Loop through the files and grab the menu items in 
  146.     // the ini file. Fills the alloc'd array with the
  147.     // menu items
  148.     for (i=0;i<uMaxItems;i++)
  149.     {
  150.         szTemp[0] = lpitem[i].szFile[0] = '\0';  
  151.         wsprintf((LPSTR)szKey,"%s%u",(LPSTR)ITEM_KEY,i+1);
  152.         GetPrivateProfileString ( ITEM_APP, szKey,
  153.             szTemp,szTemp,ITEM_MAXLEN, lpinifile);
  154.         if (*szTemp)
  155.         {
  156.             // Trim default directory off if needed
  157.             ItemListFilenameCleanup(szTemp);
  158.             lstrcpy (lpitem[i].szFile,szTemp);
  159.             upcase  (lpitem[i].szFile);
  160.             uCount++;
  161.         }
  162.     }
  163.     
  164.     // Now build the menu
  165.     if (uCount)
  166.         ItemListRestackMenu ( hMenu );
  167.     
  168.     return uCount;
  169. }
  170.  
  171. /**********************************************************
  172.     ItemListSave
  173.     
  174.     Save the menu items to the ini file.
  175.     
  176.     Returns the count of the number of menu items saved
  177. **********************************************************/
  178. UINT ItemListSave (HMENU hMenu, LPSTR lpinifile )
  179. {   
  180.     UINT    uCount = 0;
  181.     UINT    i;
  182.     char    szKey[20];
  183.     
  184.     for (i=0;i<uMaxItems;i++)
  185.     {         
  186.         if (*lpitem[i].szFile)                   
  187.         {
  188.             wsprintf((LPSTR)szKey,"%s%u",(LPSTR)ITEM_KEY,i+1);
  189.             upcase(lpitem[i].szFile);
  190.             WritePrivateProfileString(ITEM_APP,szKey,
  191.                 lpitem[i].szFile,lpinifile);
  192.             uCount++;
  193.         }
  194.     }
  195.     
  196.     return uCount;        
  197. }
  198.  
  199. /**********************************************************
  200.     ItemListAdd
  201.     
  202.     Add a new menu item to the list.  If the menu item is
  203.     already on the list, then force it to the top of the
  204.     list.  If it is not already there, then we place it 
  205.     on the top and drop the bottom one off.
  206.     
  207.     Returns the queue number where the item was placed.
  208.     If unsuccesful, returns 0.
  209. **********************************************************/
  210. UINT ItemListAdd  (HMENU hMenu, LPSTR lpentry)
  211. {
  212.         
  213.     if (lstrlen(lpentry) > ITEM_MAXLEN)
  214.         return 0;
  215.     
  216.     // Remove the directory from the filename
  217.     ItemListFilenameCleanup(lpentry);
  218.     
  219.     upcase(lpentry);    
  220.     
  221.     // If it's already there, remove it
  222.     if (ItemListFind(hMenu,lpentry) > 0)
  223.         ItemListRemove ( hMenu, lpentry );
  224.     
  225.     // Now set the menu item in it's place
  226.     return ItemListSet ( hMenu, lpentry, 1 );
  227. }
  228.  
  229. /**********************************************************
  230.     ItemListSet
  231.     
  232.     Sets a menu item in a certain position in the menu.
  233.     
  234.     Returns the queue number where the item was placed.
  235.     If unsuccesful, returns 0.
  236. **********************************************************/
  237. UINT ItemListSet ( HMENU hMenu, LPSTR lpentry, UINT uItem )
  238. {                
  239.     int        i;
  240.     
  241.     if (lstrlen(lpentry) > ITEM_MAXLEN)
  242.         return 0;
  243.  
  244.     if (uItem < 1 || uItem > uMaxItems)
  245.         return 0;
  246.  
  247.     // Remove the directory, if any    
  248.     ItemListFilenameCleanup(lpentry);
  249.  
  250.     // Loop from the top copying each string down the array
  251.     // list
  252.     for (i=uMaxItems;i>0;i--)
  253.         lstrcpy (lpitem[i].szFile,lpitem[i-1].szFile);
  254.  
  255.     // Place the new element in the list    
  256.     lstrcpy (lpitem[uItem-1].szFile,lpentry);
  257.     
  258.     // Rebuild the menu with the new items
  259.     ItemListRestackMenu(hMenu);
  260.     
  261.     return uItem;        
  262. }
  263.  
  264. /**********************************************************
  265.     ItemListRemove
  266.     
  267.     Removes a menu item from the list
  268.     
  269.     Returns the queue number of the item that was removed.
  270.     If unsuccesful, returns 0.
  271. **********************************************************/
  272. UINT ItemListRemove (HMENU hMenu, LPSTR lpentry)
  273. {
  274.     UINT    i=0;         
  275.     UINT    uItem;
  276.         
  277.     if (lstrlen(lpentry) > ITEM_MAXLEN)
  278.         return 0;
  279.     
  280.     ItemListFilenameCleanup(lpentry);
  281.         
  282.     upcase(lpentry);
  283.     if ((uItem = ItemListFind(hMenu,lpentry)) ==0)
  284.         return 0;
  285.         
  286.     for (i=uItem;i<=uMaxItems;i++)
  287.            lstrcpy (lpitem[i-1].szFile,lpitem[i].szFile);
  288.     
  289.     lpitem[uMaxItems].szFile[0] = '\0';
  290.  
  291.     ItemListRestackMenu(hMenu);
  292.  
  293.     return uItem;
  294.     
  295. }
  296.  
  297. /**********************************************************
  298.     ItemListFind
  299.     
  300.     Finds a string in the menu.
  301.     
  302.     Returns the queue number where the item was found.
  303.     If unsuccesful, returns 0.
  304. **********************************************************/
  305. UINT ItemListFind (HMENU hMenu, LPSTR lpentry)
  306. {                            
  307.     UINT    i;
  308.         
  309.     if (lstrlen(lpentry) > ITEM_MAXLEN)
  310.         return 0;
  311.  
  312.     upcase(lpentry);
  313.     for (i=1;i<=uMaxItems;i++)
  314.         if (lstrcmp(lpitem[i-1].szFile,lpentry)==0)
  315.             return i;
  316.             
  317.     return 0;
  318. }
  319.  
  320. /**********************************************************
  321.     ItemListRestackMenu
  322.     
  323.     Rebuilds the menu in its entirety based on the current
  324.     array list.
  325.     
  326. **********************************************************/
  327. VOID ItemListRestackMenu ( HMENU hMenu )
  328. {   
  329.     UINT    uCount=0, i;
  330.     char    szItem[ITEM_MAXLEN];
  331.               
  332.     // Start at the bottom of the menu and remove
  333.     // all menu items up to, and including, the separator.
  334.     for (i=0;i<uMaxItems;i++)
  335.         RemoveMenu ( GetSubMenu(hMenu,uSubMenu), i+ITEM_OFFSET, MF_BYCOMMAND);
  336.     ItemListRemoveSeparator(hMenu);
  337.     
  338.     // Now add the separator to ensure it's always there
  339.     ItemListAddSeparator(hMenu);
  340.         
  341.     // Now recompile the menu
  342.     uCount=0;
  343.     for (i=0;i<uMaxItems;i++)
  344.     {
  345.         if (*lpitem[i].szFile)
  346.         {   
  347.             wsprintf((LPSTR)szItem,"&%u. %s",uCount+1,(LPSTR)lpitem[i].szFile);
  348.             AppendMenu ( GetSubMenu(hMenu,uSubMenu), MF_BYCOMMAND | MF_STRING, ITEM_OFFSET+uCount,(LPSTR)szItem);
  349.             uCount++;
  350.         }
  351.     }
  352.  
  353.     if (!uCount)
  354.         ItemListRemoveSeparator(hMenu);        
  355. }
  356.  
  357. /**********************************************************
  358.     upcase
  359.     
  360.     Converts a string to uppercase
  361.     
  362. **********************************************************/
  363. VOID upcase(LPSTR lpszStr)
  364. {
  365.     while(*lpszStr++ = (char) toupper(*lpszStr));
  366. }
  367.  
  368. /**********************************************************
  369.     ItemListAddSeparator
  370.     
  371.     Appends a menu separator to the uSubMenu
  372.     
  373.     Returns the position append to or 0 if unsuccessful.
  374. **********************************************************/
  375. UINT ItemListAddSeparator(HMENU hMenu)
  376. {
  377.     if (!ItemListHasSeparator(hMenu))
  378.         return AppendMenu ( GetSubMenu(hMenu,uSubMenu), 
  379.                 MF_BYCOMMAND | MF_SEPARATOR, IDM_ITEMLISTSEPARATOR,NULL);        
  380.     return 0;        
  381. }
  382.  
  383. /**********************************************************
  384.     ItemListRemoveSeparator
  385.     
  386.     Removes a menu separator from the uSubMenu
  387.     
  388.     Returns the queue number where the item was removed.
  389.     If unsuccessful, returns 0.
  390. **********************************************************/
  391. UINT ItemListRemoveSeparator (HMENU hMenu)
  392. {
  393.     if (ItemListHasSeparator(hMenu))
  394.         return RemoveMenu(GetSubMenu(hMenu,uSubMenu),
  395.                 IDM_ITEMLISTSEPARATOR,MF_BYCOMMAND);
  396.     return 0;
  397. }
  398.  
  399. /**********************************************************
  400.     ItemListHasSeparator
  401.     
  402.     Check to see if we have a separator.
  403.     
  404.     Returns TRUE if found, FALSE otherwise.
  405. **********************************************************/
  406. BOOL ItemListHasSeparator (HMENU hMenu)
  407. {
  408.     if (GetMenuState (GetSubMenu(hMenu,uSubMenu), 
  409.                 IDM_ITEMLISTSEPARATOR, MF_BYCOMMAND)==-1)
  410.         return FALSE;
  411.     return TRUE;    
  412. }
  413.  
  414. /**********************************************************
  415.     ItemListGetFilename
  416.     
  417.     Returns the filename of the parameter passed.
  418.     
  419.     Returns TRUE if found, FALSE otherwise.
  420. **********************************************************/
  421. BOOL ItemListGetFilename ( WPARAM wId, LPSTR lpfilename )
  422.  
  423. {
  424.     int        iIndex = (int)(wId-IDM_ITEMLISTSEPARATOR-1);
  425.     char    szTemp[ITEM_MAXLEN];
  426.         
  427.     if (iIndex < 0 || iIndex >= (int)uMaxItems)
  428.         return FALSE;
  429.         
  430.     lstrcpy ( szTemp, lpitem[iIndex].szFile);
  431.     if (*szTemp)
  432.     {   
  433.         lstrcpy ( lpfilename, (LPSTR)szTemp);
  434.         return TRUE;
  435.     }
  436.     return FALSE;
  437. }
  438.  
  439. /**********************************************************
  440.     ItemListFilenameCleanup
  441.     
  442.     Removes the default directory from the filename.  This
  443.     function can be suppressed if the default directory
  444.     is initialized to squash "".
  445.     
  446. **********************************************************/
  447. VOID ItemListFilenameCleanup(LPSTR lpfile)
  448.  
  449. {
  450.     char    szTemp[ITEM_MAXLEN];
  451.     UINT    i,j,loop;
  452.     char    *pdest;
  453.  
  454.     if (*szDefaultDir)    
  455.     {
  456.         lstrcpy (szTemp,lpfile);
  457.         pdest = strstr(szTemp,szDefaultDir);
  458.         if (pdest!=NULL)
  459.         {
  460.             loop = lstrlen(szTemp) - lstrlen(szDefaultDir);
  461.             j=0;
  462.             for (i=LOWORD(lstrlen(szDefaultDir))+1;i<LOWORD(lstrlen(szTemp));i++)
  463.             {
  464.                 if (szTemp[i] != '\\')
  465.                     szTemp[j]=szTemp[i];
  466.                 j++;
  467.             }
  468.             szTemp[j]='\0';
  469.             
  470.         }
  471.         lstrcpy (lpfile,szTemp);
  472.     }
  473.     
  474. }        
  475.